// 1. 简单模式
function func1(a: string): string {
    return '';
}

// 2. function值表示
let func2: (a: string) => string = function (a: string): string {
    return ''
}

// 3. 封装function的类型
type callback = (a: string) => string;

let func3: callback = function (b) {
    return ''
}

// 4. interface封装的写法
interface ICallback {
    (a: string): string
}

let func4: ICallback = function (c) {
    return ''
}

// ? 代表可选参数
function css(el: HTMLElement, attr: string, val?: any) {

}

let div = document.querySelector('div');
div && css(div, 'width', '100px')
div && css(div, 'width')


// 函数参数默认值，默认值带有类型推到
function sort(items: Array<number>, order = 'desc') { }

sort([1, 2, 3])
sort([1, 2, 3], 'asc')

// 参数默认值限制取值
function sort2(items: Array<number>, order: 'desc' | 'asc' = 'desc') { }


// 剩余参数
interface IObj {
    [key: string]: any;
}


function merge(target: IObj, ...others: Array<IObj>) {
    // 浅拷贝 Object.assign 属性“assign”在类型“ObjectConstructor”上不存在。是否需要更改目标库? 
    // 请尝试将 “lib” 编译器选项更改为“es2015”或更高版本。
    // 添加:
    // "compilerOptions": {
    //     "target": "ES5",
    //     "lib": [ "dom", "es5", "es2015.promise" ,"es2015", "es2017"],
    // },
    return Object.assign(target, ...others);
}

function merge2(target: IObj, ...others: Array<IObj>) {
    return others.reduce((prev, current) => {
        prev = Object.assign(prev, current);
        return prev;
    }, target)
}

let newObj = merge({ x: 1 }, { y: 2 }, { z: 3 })
let newObj2 = merge2({ x: 1 }, { y: 2 }, { z: 3 })


